package com.itheima.sh.exception;

import com.google.common.collect.ImmutableMap;
import com.itheima.sh.response.Result;
import com.itheima.sh.response.StatusCode;
import org.apache.log4j.Logger;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.io.FileNotFoundException;

/**
 * @Description:  全局异常处理器
 * @Version: V1.0
 */
@RestControllerAdvice  // 组合注解
public class ExceptionCatch {
    private static final Logger LOGGER = Logger.getLogger(ExceptionCatch.class);

    @ExceptionHandler(BusinessException.class)  // 拦截的是 BusinessException 自定义异常
    public Result catchBusinessException(BusinessException ex) {
        // 记日志，发短信/邮件
        LOGGER.error(ex);

        ex.printStackTrace();

        return Result.errorResult(ex.getStatusCode());
    }


    //使用EXCEPTIONS存放异常类型和错误代码的映射，ImmutableMap的特点的一旦创建不可改变，并且线程安全
    private static ImmutableMap<Class<? extends Throwable>,Result> EXCEPTIONS;
    //使用builder来构建一个异常类型和错误代码的异常
    protected static ImmutableMap.Builder<Class<? extends Throwable>,Result> builder = ImmutableMap.builder();

    @ExceptionHandler(Exception.class)  // 拦截的是Exception 不可预知异常
    public Result catchException(Exception ex) {
        // 记日志，发短信/邮件
        LOGGER.error(ex);

        if (EXCEPTIONS == null) {
            EXCEPTIONS = builder.build();
        }

        // 1 先到 EXCEPTIONS 根据key 得到Result结果返回
        Result result = EXCEPTIONS.get(ex.getClass());
        if (result == null) {
            // 2 没有找到 统一响应 99999 异常
            result = Result.errorResult(StatusCode.SYS_ERROR);
        }

        return result;

    }



    static {
        //在这里加入一些基础的异常类型判断
        builder.put(HttpMessageNotReadableException.class,
                Result.errorResult(StatusCode.PARAM_INVALID));
        builder.put(ArithmeticException.class,
                Result.errorResult(StatusCode.ARITHMETIC_ERROR));
        builder.put(FileNotFoundException.class,
                Result.errorResult(StatusCode.ARITHMETIC_ERROR));
    }

}
